#include "GLabel.h"

#include "GFonts.h"
#include "Object.h"

struct _GLabel
{
        GWidget parent_instance;
        //
        const unsigned char *text;
        //
        uint16_t text_color;
        uint16_t background_color;
        /* 上一次的实际显示区域 */
        uint16_t pre_coord[4];
        bool     is_wchar;
};

static uint16_t
g_label_get_min_width(const GLabel *self)
{
        uint16_t             width;
        const unsigned char *t = self->text;
        /* 判断字符是中文还是西文 */
        for (width = 0; *t; ++t)
                if (*t < 128)
                        width += 8;
                else
                        width += 16;
        return width;
}

static uint16_t
g_label_get_min_height(GLabel *self)
{
        return 16;
}

static void
g_label_render_font(const GLabel *self, Screen *screen, const unsigned char *ch)
{
        for (short j = 0; j < 16; ++j) {
                uint8_t flag = 0x80;
                for (short i = 0; i < 8; ++i) {
                        if (flag & ch[j]) {
                                screen_draw_pixel(screen, self->text_color);
                        } else {
                                screen_draw_pixel(screen,
                                                  self->background_color);
                        }
                        flag >>= 1;
                }
        }
}

/**
 * @brief
 * 若当前渲染尺寸比原尺寸小，则需要用空白重新填充原区域，防止影响显示效果。
 */
static void
g_label_pre_render(const GLabel *self)
{
        if (self->pre_coord[2] == 0)
                return;
        Screen *screen = screen_new_from_global();
        screen_set_draw_area(screen,
                             self->pre_coord[0],
                             self->pre_coord[1],
                             self->pre_coord[2],
                             self->pre_coord[3]);
        for (uint16_t i = self->pre_coord[0]; i <= self->pre_coord[2]; ++i)
                for (uint16_t j = self->pre_coord[1]; j <= self->pre_coord[3];
                     ++j)
                        screen_draw_pixel(screen, screen_background_color);
}

static void
g_label_render(GLabel  *self,
               uint16_t startX,
               uint16_t startY,
               uint16_t endX,
               uint16_t endY)
{
        if (G_WIDGET(self)->force_render)
                G_WIDGET(self)->is_update = false;

        if (G_WIDGET(self)->is_update)
                return;

        startX = g_align_scale_sx(G_WIDGET(self)->align,
                                  startX,
                                  endX,
                                  g_widget_get_min_width(G_WIDGET(self)));
        startY = g_align_scale_sy(G_WIDGET(self)->align,
                                  startY,
                                  endY,
                                  g_widget_get_min_height(G_WIDGET(self)));

        /* 去掉边框获得实际渲染距离 */
        startX += G_WIDGET(self)->margin;
        startY += G_WIDGET(self)->margin;
        /* 渲染结束的坐标 */
        endX = startX + g_label_get_min_width(self) - 1;
        endY = startY + 15;

        if (startX > self->pre_coord[0] || endX < self->pre_coord[2] ||
            G_WIDGET(self)->force_render) {
                g_label_pre_render(self);
        }
        self->pre_coord[0] = startX;
        self->pre_coord[1] = startY;
        self->pre_coord[2] = endX;
        self->pre_coord[3] = endY;

        Screen *screen     = screen_new_from_global();
        /* 逐字渲染 */
        for (short i = 0; self->text[i]; ++i) {
                const unsigned char *ch = g_font_get_pointer(self->text[i]);
                if (self->text[i] < 128) {
                        screen_set_draw_area(screen,
                                             startX,
                                             startY,
                                             startX + 7,
                                             startY + 15);
                        g_label_render_font(self, screen, ch);
                        startX += 8;
                } else {
                        screen_set_draw_area(screen,
                                             startX,
                                             startY,
                                             startX + 7,
                                             startY + 15);
                        g_label_render_font(self, screen, ch);
                        screen_set_draw_area(screen,
                                             startX + 8,
                                             startY,
                                             startX + 15,
                                             startY + 15);
                        g_label_render_font(self, screen, ch + 16);
                        startX += 16;
                }
        }
        /* 更新小部件状态 */
        G_WIDGET(self)->is_update = true;
}

GWidget *
g_label_new(void)
{
        GLabel *self = object_new(GLabel);
        g_widget_init(G_WIDGET(self),
                      G_WIDGET_NUMS_CALLBACK(g_label_get_min_width),
                      G_WIDGET_NUMS_CALLBACK(g_label_get_min_height),
                      G_WIDGET_RENDER(g_label_render));
        self->text             = NULL;
        self->text_color       = 0x0000;
        self->background_color = 0xffff;
        for (uint8_t i = 0; i < 4; ++i)
                self->pre_coord[i] = 0;
        return G_WIDGET(self);
}

void
g_label_set_text(GLabel *self, const unsigned char *text)
{
        self->text                = text;
        G_WIDGET(self)->is_update = false;
}

void
g_label_set_text_color(GLabel *self, const uint16_t color)
{
        self->text_color          = color;
        G_WIDGET(self)->is_update = false;
}

void
g_label_set_background_color(GLabel *self, const uint16_t color)
{
        self->background_color    = color;
        G_WIDGET(self)->is_update = false;
}
